home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / files.swg / 0075_Combined Real and DPMI File Handle Exten.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-05-26  |  16.7 KB  |  560 lines

  1. {
  2. From: "CLAUS FISCHER" <WI00227@wipool.wifo.uni-mannheim.de>
  3.  
  4. I had found the Extend.Pas and PExted.pas on SWAG.
  5. First provides 255 File in DOS, second in protcted mode.
  6. Now I had mixed them together and I wish to give this to
  7. SWAG. Where should I post this?
  8.  
  9. (*** 3 Files: ***)
  10.  255DEMO.PAS  (Extend Version with StdErr)
  11.  FILEPLUS.PAS (was EXTEND.PAS)
  12.  DOSMEM.PAS   (was SHRINK.PAS)
  13. {-------------------------------snipp--------------------------------}
  14.   program Test255Files;
  15.  
  16. uses fileplus,       { <--- This is the magic line that does
  17. everything }
  18.      Dos;
  19.  
  20. const MaxCount = 255;
  21.  
  22. type FileArray = array[1..MaxCount] of text;
  23.  
  24. var Count: integer;
  25.     StdErr: Text;
  26.     F: ^FileArray;
  27.     I: integer;
  28.     Num: string[6];
  29.  
  30. procedure stderror(var f:text);
  31. var
  32.     tmpfile:text;
  33. begin
  34.   assign(tmpfile,''); (* stdoutput *)
  35.   rewrite(tmpfile);
  36.   move(tmpfile, f, sizeof(f));
  37.   textrec(f).handle:= 2;
  38.   close(tmpfile);
  39. end;
  40.  
  41. begin
  42. write('Hello!! I''m running under ');
  43. {$IFDEF MSDOS}writeln('MsDos REAL-Mode');
  44. {$ELSE} writeln('DPMI Protected Mode');
  45. {$ENDIF}
  46. new(F);            { Use heap because of large size of this array }
  47. writeln('Opening files...');
  48. Stderror(StdErr);
  49. writeln( Stderr, '(Handle Stderr) ',TextRec(StdErr).Handle );
  50. writeln( Output, '(Handle Stdout) ',TextRec(Output).Handle );
  51. write( Output, '(Handle:FileNo) ');
  52. I := 0;
  53. repeat
  54.   inc(I);
  55.   str(I,Num);
  56.   assign(F^[I],'junk' + num + '.txt');
  57.   {$I-}
  58.   rewrite(F^[I]);
  59.   write( OutPut, i:4,':',TextRec(f^[i]).Handle );
  60.   {$I+}
  61. until ioresult <> 0;
  62. writeln(output);
  63. Count := I - 1;
  64. writeln('Successfully opened ', Count, ' files at the same time.
  65. Writing to each file...');
  66. for I := 1 to Count do
  67.   writeln(F^[I], 'This is a test.');
  68. writeln('Closing and erasing each file...');
  69. for I := 1 to Count do
  70.   begin
  71.   close(F^[I]);
  72.   erase(F^[I])
  73.   end;
  74. writeln('Done.')
  75. end.
  76. {----------------------snapp----------------------------------------}
  77.  
  78. {---------------------snipp---------------------------------------}
  79. {$I-,O-,R-}
  80.  
  81. unit fileplus; {origin name Extend}
  82.  
  83. {Patch V1.0 94-12 Claus Fischer for}
  84. {REF: MsDos-Real-Mode: Scott Bussinger}
  85. {     DPMI:          : Kim Kokkonen, TurboPower Software}
  86. {     catched up on SIMTEL-Archieve and SWAG-List}
  87.  
  88. {FILEPLUS Patch Claus Fischer}
  89. { Changes:
  90.   Main feater: Use Real-Mode and DPMI-Mode with the same Unit.
  91.   I have disabled DOS 2.xx Management because its not necessary for
  92. me.
  93.   The SHRINK-Unit is now named as DosMem.Pas.
  94.   The futur check of MSDOS-Version is removed, because further MSDOS
  95. vers
  96.   will shure support the prefix features. The market use this.
  97.   The DPMIExtendHandles-Function was changed to Procedure, so its
  98. equal
  99.   to MSDOSExtendHandles (not neccesary, but looks pretty).
  100.   Claus Fischer
  101.   WI00227@WIPOOL.WIFO.UNI-MANNHEIM.DE
  102. }
  103.  
  104. {EXTEND Version Scott Bussinger}
  105. { This unit allows a program to open more than the standard DOS
  106. maximum of 20
  107.   open files at one time.  You must also be sure to set a FILES=XX
  108. statement
  109.   in your CONFIG.SYS file.
  110.   (DISABLED: This program installs a special interrupt handler
  111.          under DOS 2.x, some semi-documented features under
  112.          DOS 3.x prior to DOS 3.3 and the DOS extend files
  113.          call under DOS 3.3 or later. C.F.)
  114.   This unit USES the DOS unit and should be used BEFOR ANY OTHER UNTIS
  115.   other than the DOS unit.  This code was based upon earlier work by
  116.   Randy Forgaard, Bela Lubkin and Kim Kokkonen.  See EXTEND.DOC for
  117.   more information.
  118.  
  119.   Scott Bussinger
  120.   Professional Practice Systems
  121.   110 South 131st Street
  122.   Tacoma, WA  98444
  123.   (206)531-8944
  124.   Compuserve [72247,2671] }
  125.  
  126. { ** Revision History **
  127.   1 EXTEND.PAS 9-Mar-89,`SCOTT' First version using TLIB -- Based on
  128. 3.2
  129.   2 EXTEND.PAS 15-Sep-89,`SCOTT'
  130.        Added SwapVectorsExtend procedure
  131.            Put handle table into DOS memory
  132.        Use DOS 3.3 extended handles function when available
  133.   3 EXTEND.PAS 2-Oct-89,`SCOTT'
  134.        Fixed bug in determining the DOS version
  135.   4 EXTEND.PAS 5-Oct-89,`SCOTT'
  136.            Yet another bug in the DosVersion detection
  137.   5 EXTEND.PAS 19-Nov-90,`SCOTT'
  138.            New version of EXTEND that is compatible with Turbo Pascal
  139. 6.0
  140.        Modified the documentation and version numbers to be less
  141. confusing
  142.   ** Revision History ** }
  143.  
  144. {PEXTEND    DPMI-Version Kim Kokkonen
  145.  ------------------------------------------------------------------
  146.  This unit provides a single function, DpmiExtendHandles, for
  147.  extending the file handle table for DOS protected mode applications
  148.  under Borland Pascal 7.0.
  149.  
  150.  The standard DOS call for this purpose (AH = $67) does odd things to
  151.  DOS memory when run from a BP7 pmode program. If you Exec from a
  152.  program that has extended the handle table, DOS memory will be
  153.  fragmented, leaving a stranded block of almost 64K at the top of DOS
  154.  memory. The function implemented here avoids this problem.
  155.  
  156.  If you haven't used an ExtendHandles function before, note that you
  157.  cannot get more handles than the FILES= statement in CONFIG.SYS
  158.  allows. (Other utilities such as FILES.COM provided with QEMM do the
  159.  same thing.) However, even if you have FILES=255, any single program
  160.  cannot open more than 20 files (and DOS uses up 5 of those) unless
  161.  you use a routine like DpmiExtendHandles. This routine allows up to
  162.  255 open files as long as the FILES= statement provides for them.
  163.  
  164.  This code works only for DOS 3.0 or later. Since (to my knowledge)
  165.  DPMI cannot be used with earlier versions of DOS, the code doesn't
  166.  check the DOS version.
  167.  
  168.  Don't call this function more than once in the same program.
  169.  
  170.  Version 1.0,
  171.    Written 12/15/92, Kim Kokkonen, TurboPower Software
  172. }
  173.  
  174. interface
  175.  
  176. (* delted(0) of Dos 2.11 Version-Managament *)
  177. (* procedure SwapVectorsExtend;
  178.   { Swap interrupt vectors taken over by Extend unit with system
  179. vectors }
  180. *)
  181. (* END of delted(0) *)
  182.  
  183. implementation
  184.  
  185. uses Dos,
  186.      {$IFDEF MSDOS} DosMem;
  187.      {$ELSE}        WinApi;
  188.      {$ENDIF}
  189.  
  190. (* deleted(1) DOS 2.11 Ver ... *)
  191. (* var ExitSave: pointer;                           { Previous exit
  192. procedure }
  193.     OldInt21: pointer;                           { Save old INT 21 }
  194. *)
  195. (* END of delted(1) *)
  196.  
  197. (* Deleted(2) ...   DOS 2.11 Ver *)
  198. (*
  199. {$L EXTEND }
  200. procedure ExtendInit; external;                  { Initialize
  201. interrupt handler }
  202. procedure ExtendHandler; external;               { Replacement INT 21
  203. handler }
  204. *)
  205. (* End of delted(2) *)
  206.  
  207. (* ... deleted(3) DOS 2.11 Ver.... *)
  208. (*
  209. procedure SwapVectorsExtend;
  210.   { Swap interrupt vectors taken over by Extend unit with system
  211. vectors }
  212.   var TempVector: pointer;
  213.   begin
  214.   if lo(DosVersion) = 2 then
  215.     begin
  216.     GetIntVec($21,TempVector);                   { Swap the INT 21
  217. vectors }
  218.     SetIntVec($21,OldInt21);
  219.     OldInt21 := TempVector
  220.     end
  221.   end;
  222. *)
  223. (* END of Deleted(3) *)
  224.  
  225.  
  226. {$IFDEF MSDOS}
  227. procedure MSDOSExtendHandles;
  228. (* My Patch of MSDOS Scott Bussinger Version *)
  229.   { Install the extended handles interrupt.  No files (other than
  230.     standard handles) should be open when unit starts up. }
  231.  
  232. type   HandleArray = array[0..254] of byte;        { Room for 255
  233. handles }
  234.        HandleArrayPtr = ^HandleArray;
  235.  
  236.   var Regs: Registers;
  237.       DosMemory: pointer;                          { Pointer to
  238. memory gained from DOS }
  239.       OldHandleTable: HandleArrayPtr;              { Pointer to
  240. original table }
  241.       OldNumHandles: byte;                         { Original number
  242. of handles }
  243.   begin
  244.  
  245.   if lo(DosVersion) <= 2
  246.    then {Patch KISS!} exit;
  247.  
  248.   (* deleted(4) DOS 2.11 ..... *)
  249.   (*
  250.     begin
  251.     GetIntVec($21,OldInt21);                     { Install interrupt
  252. handler under DOS 2.x }
  253.     ExtendInit;                                  { Initialize the
  254. interrupt handler }
  255.     SetIntVec($21,@ExtendHandler)
  256.     end
  257.    else
  258.    *)
  259.    (* END of deleted(4) *)
  260.  
  261.    (* deleted(5) schnick-schnack: MickySoft will support further *)
  262.    (*
  263.       if (lo(DosVersion)>=4) or (hi(DosVersion)>=30) { Does this DOS
  264. version support the handles call? }
  265.        then
  266.         begin
  267.     DosDispose(DosMemory);                   { Free up the DOS memory
  268. block so that the next function will succeed }
  269.     with Regs do
  270.           begin
  271.           AH := $67;                             { Tell DOS to allow
  272. us 255 handles }
  273.           BX := 255;                             { KEEP THIS NUMBER
  274. ODD TO AVOID BUG IN SOME VERSIONS OF DOS 3.3!! }
  275.           MsDos(Regs)
  276.       end
  277.     end
  278.        else  begin
  279.    *)
  280.    (* END of delted(5) *)
  281.  
  282.  
  283.    DosNewShrink(DosMemory,sizeof(HandleArray));
  284.    if DosMemory = nil then exit;
  285.        { There wasn't enough memory for a handle table, so just quit }
  286.    begin {else}
  287.  
  288.     { Initialize new handles as unused          *1* }
  289.     { Get old table length                  *2* }
  290.     { Save address of old table                 *3* }
  291.     { Set new table length                  *4* }
  292.     { Point to new handle table                 *5* }
  293.     { Copy the current handle table to the new handle table *6* }
  294.  
  295.     fillchar(DosMemory^,sizeof(HandleArray),$FF);          (*1*)
  296.     OldNumHandles := mem[prefixseg:$0032];                 (*2*)
  297.     OldHandleTable := pointer(ptr(prefixseg,$0034)^);      (*3*)
  298.     mem[prefixseg:$0032] := sizeof(HandleArray);           (*4*)
  299.     pointer(meml[prefixseg:$0034]) := DosMemory;           (*5*)
  300.     move(OldHandleTable^,DosMemory^,OldNumHandles)         (*6*)
  301.    end
  302.   end; (* of MSDOSExtenHandles *)
  303. {$ENDIF} {of IFDEF MSDOS}
  304.  
  305. {$IFNDEF MSDOS} {.= WINAPI}
  306. procedure DPMIExtendHandles;
  307.    const Handles = 255; (* added *)
  308. (* My Patch of MSDOS Kim Kokkonen Version *)
  309. (* Orginal was: function DpmiExtendHandles(Handles : Byte) : Word; *)
  310.   type DosMemRec = record
  311.             Sele, Segm : Word;
  312.            end;
  313.    var
  314.     OldTable : Pointer;
  315.     OldSize : Word;
  316.     NewTable : Pointer;
  317.     DosMem : DosMemRec;
  318.   begin
  319.      (* DEL: DpmiExtendHandles := 0; PROCEDURE replaced *)
  320.      (* DEL: if Handles <= 20 then Exit; CONST replaced *)
  321.  
  322.      {Allocate new table area in DOS memory}
  323.      LongInt(DosMem) := GlobalDosAlloc(Handles);
  324.      if LongInt(DosMem) = 0 then
  325.     exit; (* add *)
  326.  
  327.       (* DEL: begin DpmiExtendHandles := 8;Exit; end; PROCEDURE
  328. replaced *)
  329.  
  330.       {Initialize new table with closed handles}
  331.     NewTable := Ptr(DosMem.Sele, 0);(*1*)
  332.     FillChar(NewTable^, Handles, $FF);(*1*)
  333.  
  334.       {Copy old table to new. Assume old table in PrefixSeg}
  335.     OldTable := Ptr(PrefixSeg, MemW[PrefixSeg:$34]);
  336.     OldSize := Mem[PrefixSeg:$32];
  337.     move(OldTable^, NewTable^, OldSize);
  338.  
  339.       {Set new handle table size and pointer}
  340.     Mem[PrefixSeg:$32] := Handles;
  341.     MemW[PrefixSeg:$34] := 0;
  342.     MemW[PrefixSeg:$36] := DosMem.Segm;
  343.   end; (* of DPMIExtendHandles *)
  344. {$ENDIF} {of IFNDEF MSDOS}
  345.  
  346.  
  347. (* deleted(6) DOS 2.11 Ver ... *)
  348. (*
  349. {$F+}
  350. procedure ExitHandler;
  351. {$F-}
  352.   { Uninstall the extended handles interrupt.  All files (other
  353.     than standard handles) should be closed before unit exits. }
  354.   begin
  355.   ExitProc := ExitSave;                          { Chain to next exit
  356. routine }
  357.   SwapVectorsExtend                              { Restore original
  358. interrupt vectors }
  359.   end;
  360. *)
  361. (* END of delted(6) *)
  362.  
  363. begin (* of Install *)
  364. (* deleted(7) DosVer 2.11 ... *)
  365. (* ExitSave := ExitProc;                            { Remember the
  366. previous exit routine }
  367.    ExitProc := @ExitHandler;  { Install our exit routine }
  368. *)
  369. (* END of delted(7) *)
  370.  
  371.  
  372. {$IFDEF MSDOS}
  373.   MSDOSExtendHandles; { Enable the extra handles }
  374. {$ELSE}
  375.   DPMIExtendHandles;
  376. {$ENDIF}
  377. end.
  378. {-------------------------------snapp--------------------------------}
  379.  
  380. {-------------------------------snipp-------------------------------}
  381. unit DosMem;
  382.  
  383. {$IFDEF DPMI}  *** Only Real-Mode! *** {$ENDIF}
  384. {$IFDEF WINDOWS} *** Only Dos-Real-Mode *** {$ENDIF}
  385. {$IFDEF OS2} *** Only Dos-Real-Mode *** {$ENDIF}
  386.  
  387. { This unit allows you to allocate memory from the DOS memory pool
  388. rather than
  389.   from the Turbo Pascal heap.  It also provides a procedure for
  390. shrinking the
  391.   current program to free up DOS memory.
  392.  
  393.   Scott Bussinger
  394.   Professional Practice Systems
  395.   110 South 131st Street
  396.   Tacoma, WA  98444
  397.   (206)531-8944
  398.   Compuserve [72247,2671] }
  399.  
  400. { ** Revision History **
  401.   1 SHRINK.PAS 15-Sep-89,`SCOTT' Initial version of SHRINK unit
  402.   2 SHRINK.PAS 19-Oct-90,`SCOTT'
  403.        Added support for Turbo Pascal 6's new heap manager
  404.   ** Revision History ** }
  405.  
  406. interface
  407.  
  408. procedure DosNew(var P: pointer;
  409.                      Bytes: word);
  410.   { Get a pointer to a chunk of memory from DOS.  Returns NIL if
  411.     sufficient DOS memory is not available. }
  412.  
  413. procedure DosDispose(var P: pointer);
  414.   { Return an allocated chunk of memory to DOS.  Only call this
  415. function
  416.     with pointers allocated with DosNew or DosNewShrink. }
  417.  
  418. procedure DosNewShrink(var P: pointer;
  419.                            Bytes: word);
  420.   { Get a pointer to a chunk of memory from DOS, shrinking current
  421. program
  422.     to gain DOS memory if necessary.  Returns NIL if sufficient DOS
  423. memory
  424.     is not available and there is insufficient free space in the heap
  425. to
  426.     allow program to be shrunk to accomodate the request. }
  427.  
  428. function Linear(P: pointer): longint;
  429.   { Return the pointer as a linear longint value }
  430.  
  431. implementation
  432.  
  433. uses Dos;
  434.  
  435. const DosOverhead = 1;                           { Extra number of
  436. paragraphs that DOS requires in overhead for MCB chain }
  437.  
  438. function Linear(P: pointer): longint;
  439.   { Return the pointer as a linear longint value }
  440.   begin
  441.   Linear := (longint(seg(P^)) shl 4) + ofs(P^)
  442.   end;
  443.  
  444. procedure DosNew(var P: pointer;
  445.                      Bytes: word);
  446.   { Get a pointer to a chunk of memory from DOS.  Returns NIL if
  447.     sufficient DOS memory is not available. }
  448.   var SegsToAllocate: word;
  449.       Regs: Registers;
  450.   begin
  451.   SegsToAllocate := (Bytes+15) shr 4;            { DOS allocates
  452. memory in paragraph sized pieces only }
  453.   with Regs do
  454.     begin
  455.     AH := $48;
  456.     BX := SegsToAllocate;
  457.     MsDos(Regs);
  458.     if odd(Flags)
  459.      then
  460.       P := nil                                   { No memory
  461. available }
  462.      else
  463.       P := ptr(AX,$0000)                         { Return pointer to
  464. memory block }
  465.     end
  466.   end;
  467.  
  468. procedure DosDispose(var P: pointer);
  469.   { Return an allocated chunk of memory to DOS.  Only call this
  470. function
  471.     with pointers allocated with DosNew or DosNewShrink. }
  472.   var Regs: Registers;
  473.   begin
  474.   with Regs do
  475.     begin
  476.     AH := $49;
  477.     ES := seg(P^);
  478.     MsDos(Regs)
  479.     end
  480.   end;
  481.  
  482. procedure DosNewShrink(var P: pointer;
  483.                            Bytes: word);
  484.   { Get a pointer to a chunk of memory from DOS, shrinking current
  485. program
  486.     to gain DOS memory if necessary.  Returns NIL if sufficient DOS
  487. memory
  488.     is not available and there is insufficient free space in the heap
  489. to
  490.     allow program to be shrunk to accomodate the request. }
  491.   var BytesToAllocate: word;
  492.       Regs: Registers;
  493.   begin
  494.   BytesToAllocate := (((Bytes+15) shr 4) + DosOverhead) shl 4;
  495.   DosNew(P,Bytes);
  496.   { Try to get memory the easy way first }
  497.  
  498.   {$IFDEF VER60} {$DEFINE NEWHEAP} {$ENDIF}
  499.   {$IFDEF VER70} {$DEFINE NEWHEAP} {$ENDIF}
  500.  
  501.   {$IFDEF NEWHEAP}
  502.   { Check for Turbo 6's new heap manager }
  503.   if (P=nil) and (Linear(HeapEnd)-Linear(HeapPtr)>=BytesToAllocate)
  504. then
  505.     begin
  506.     { The easy method didn't work but there is sufficient space in
  507. the heap }
  508.     dec(longint(HeapEnd),longint(BytesToAllocate) shl 12);
  509.     { Move the top of the heap down }
  510.  
  511.     with Regs do
  512.       begin
  513.       AH := $4A;
  514.       BX := seg(HeapEnd^) - prefixseg - (BytesToAllocate shr 4);
  515.       ES := prefixseg;
  516.       MsDos(Regs)
  517.       end;
  518.     DosNew(P,Bytes)
  519.     { Try the DOS allocation one more time }
  520.     end
  521.   {$ELSE}
  522.   if (P=nil) and
  523.   { Handle the old free list style heap }
  524.      (  ( (ofs(FreePtr^)=0)
  525.       and (Linear(FreePtr)+$10000-Linear(HeapPtr)>=BytesToAllocate)
  526.     ) or
  527.     (
  528.      (ofs(FreePtr^)<>0)
  529.       and (Linear(FreePtr)-Linear(HeapPtr)>=BytesToAllocate)
  530.      )  )
  531.      then
  532.     begin
  533.     { The easy method didn't work but there is sufficient space in
  534. the heap }
  535.     OldFreePtr := FreePtr;
  536.     dec(longint(FreePtr),longint(BytesToAllocate) shl 12);
  537.     { Decrement the segment of the pointer to the free list }
  538.  
  539.     if ofs(OldFreePtr^) <> 0 then
  540.     { If free list is empty, then there's nothing to move }
  541.       move(OldFreePtr^,FreePtr^,$10000-ofs(OldFreePtr^));
  542.       { Otherwise, move the free list down in memory }
  543.  
  544.     with Regs do
  545.       begin
  546.       AH := $4A;
  547.       BX := seg(OldFreePtr^) + $1000 - prefixseg - (BytesToAllocate
  548. shr 4);
  549.       ES := prefixseg;
  550.       MsDos(Regs)
  551.       end;
  552.     DosNew(P,Bytes)                              { Try the DOS
  553. allocation one more time }
  554.     end
  555.   {$ENDIF}
  556.   {$IFDEF NEWHEAP}{$UNDEF NEWHEAP}{$ENDIF}
  557.   end;
  558.  
  559. end.
  560.